﻿using System;
using System.Collections.Generic;

using System.Text;
using System.Collections;
using System.Windows.Documents;
using System.Windows.Media;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Diagnostics;
using System.Timers;
using Bixas.Tangibilis.Input;
using Bixas.Tangibilis.Utility;

namespace Bixas.Tangibilis.Controls.Primitives
{
    internal class TouchThumbAdapter : TouchUIElementAdapter<TouchThumb>
    {

        private TouchCursorState CursorOne;
        private TouchCursorState CursorTwo;

        private Point OriginPointOne = new Point(0, 0);
        private Point OriginPointTwo = new Point(0, 0);

        private bool _allowRotate = true;
        private bool _allowScale = true;

        private double _latestAngle = 0;
        private double _latestScale = 0;
        private double _latestOffsetX = 0;
        private double _latestOffsetY = 0;

        private double _newAngle = 0;
        private double _newScale = 0;
        private double _newOffsetX = 0;
        private double _newOffsetY = 0;
        private double _motionSpeed;
        private long _lastetTickMotionSpeed;

        public TouchThumbAdapter(TouchThumb elementAdapted)
            : this(elementAdapted, true, true)
        { }

        public TouchThumbAdapter(TouchThumb elementAdapted, bool allowRotate, bool allowScale)
            : base(elementAdapted)
        {
            this._allowRotate = allowRotate;
            this._allowScale = allowScale;
        }

        public override void OnTouchCursorDown(RoutedEventArgs e)
        {
            base.OnTouchCursorDown(e);
            RawTouchCursorInputEventArgs args = e as RawTouchCursorInputEventArgs;
            e.Handled = true;
            base.TouchElement.Focus();
            args.Cursor.CaptureElement(this.TouchElement);

            bool flag = true;
            try
            {
                flag = InitEvents();
            }
            finally
            {
                if (flag)
                {
                    this.TouchElement.CancelDrag();
                }
            }
        }

        private bool InitEvents()
        {
            if (base.IsTouchCursorOver)
            {
                TouchElement.IsTouchDragging = true;
                bool flgMultiple = GetOriginPoints();

                TouchElement.RaiseEvent(new TouchDragStartedEventArgs(this.OriginPointOne.X, this.OriginPointOne.Y));
                if (flgMultiple)
                {
                    TouchElement.IsTouchRotating = true;
                    TouchElement.IsTouchScaling = true;
                    TouchElement.RaiseEvent(new TouchRotateStartedEventArgs());
                    TouchElement.RaiseEvent(new TouchScaleStartedEventArgs());
                };
                return true;
            }
            else
            {
                TouchElement.IsTouchDragging = false;
            }
            return false;
        }

        public override void OnTouchCursorUp(RoutedEventArgs e)
        {
            base.OnTouchCursorUp(e);
            RaiseCompleteEvents();
            InitEvents();
        }

        private void RaiseCompleteEvents()
        {
            if (_allowScale)
                TouchElement.RaiseEvent(new TouchScaleCompletedEventArgs(_newScale, false));

            if (_allowRotate)
                TouchElement.RaiseEvent(new TouchRotateCompletedEventArgs(_newAngle, false));

            TouchElement.RaiseEvent(new TouchDragCompletedEventArgs(_newOffsetX, _newOffsetY, _motionSpeed, false));
        }

        public override void OnTouchCursorLeave(RoutedEventArgs e)
        {
            base.OnTouchCursorLeave(e);
            GetOriginPoints();
        }

        public override void OnTouchCursorMove(RoutedEventArgs e)
        {
            base.OnTouchCursorMove(e);
            if (this.TouchElement.IsTouchDragging)
            {
                if (base.IsTouchCursorPressed)
                {
                    RawTouchCursorInputEventArgs Args = (RawTouchCursorInputEventArgs)e;
                    e.Handled = true;
                    UpdateTransform();
                    RaiseDeltaEvents();
                }
                else
                {

                }
            }
        }

        private void RaiseDeltaEvents()
        {

            if (_allowScale)
                TouchElement.RaiseEvent(new TouchScaleDeltaEventArgs(_newScale - _latestScale));
            _latestScale = _newScale;

            TouchElement.RaiseEvent(new TouchDragDeltaEventArgs(_newOffsetX - _latestOffsetX, _newOffsetY - _latestOffsetY, _motionSpeed));

            if (_allowRotate)
                TouchElement.RaiseEvent(new TouchRotateDeltaEventArgs(_newAngle - _latestAngle));
            _latestAngle = _newAngle;

            _latestOffsetX = _newOffsetX;
            _latestOffsetY = _newOffsetY;
        }

       private void UpdateTransform()
        {
            Point PointOne = TouchDevice.GetPosition(CursorOne.LastPosition, this.TouchElement);
            Point PointTwo = TouchDevice.GetPosition(CursorTwo.LastPosition, this.TouchElement);
            // PointOne = SafeSecurityHelperWrapper.ClientToScreen(this.TouchElement, PointOne);
            // PointTwo = SafeSecurityHelperWrapper.ClientToScreen(this.TouchElement, PointTwo);

            //Point point2 = SafeSecurityHelperWrapper.ClientToScreen(this.TouchElement, PointOne);
            // if (point2 != this._previousScreenCoordPosition)
            // {
            //this._previousScreenCoordPosition = point2;

            if (CursorOne == CursorTwo)
            {
                _newOffsetX = PointOne.X - OriginPointOne.X;
                _newOffsetY = PointOne.Y - OriginPointOne.Y;
                
                   //_newOffsetX += 1;
                //_newOffsetY = 1;
                // Added By Roberto Sonnino
                _newScale = 0;
                _newAngle = 0;

            }
            else
            {
                Vector vOrigin = Point.Subtract(OriginPointTwo, OriginPointOne);
                Vector vCurrent = Point.Subtract(PointTwo, PointOne);
                Point centerOrigin = Point.Add(OriginPointOne, Vector.Divide(vOrigin, 2));
                Point centerCurrent = Point.Add(PointOne, Vector.Divide(vCurrent, 2));

                _newScale = (vCurrent.Length - vOrigin.Length) / vOrigin.Length;
                _newAngle = Vector.AngleBetween(vOrigin, vCurrent);

                _newOffsetX = centerCurrent.X - centerOrigin.X;
                _newOffsetY = centerCurrent.Y - centerOrigin.Y;

            }

            long newtick = DateTime.Now.Second;
            _motionSpeed = Math.Abs(_newOffsetX - _latestOffsetX) / newtick - _lastetTickMotionSpeed;
            _lastetTickMotionSpeed = newtick;
        }
        //}


        private bool GetOriginPoints()
        {
            CursorTwo = null;
            CursorOne = null;

            OriginPointOne = new Point();
            OriginPointTwo = new Point();

            _latestAngle = 0;
            _latestOffsetX = 0;
            _latestOffsetY = 0;
            _latestScale = 0;

            IEnumerator enumerator = this.cursorStateObjects.Keys.GetEnumerator();
            while (enumerator.MoveNext())
            {
                TouchCursorState cursorState = ((TouchCursorState)this.cursorStateObjects[enumerator.Current]);
                if (cursorState.IsOver)
                {
                    if (CursorOne == null)
                        CursorOne = cursorState;

                    if (CursorTwo == null)
                        CursorTwo = cursorState;

                    Point position = TouchDevice.GetPosition(cursorState.LastPosition, this.TouchElement);
                    if (position.X < CursorOne.LastPosition.X)
                    {
                        CursorOne = cursorState;
                    }

                    if (position.X > CursorTwo.LastPosition.X)
                    {
                        CursorTwo = cursorState;
                    }
                }
            }

            CursorOne = CursorOne ?? CursorTwo;
            CursorTwo = CursorTwo ?? CursorOne;

            if (CursorOne != null)
            {
                OriginPointOne = TouchDevice.GetPosition(CursorOne.LastPosition, this.TouchElement);
                OriginPointTwo = TouchDevice.GetPosition(CursorTwo.LastPosition, this.TouchElement);
                //   OriginPointOne = SafeSecurityHelperWrapper.ClientToScreen(this.TouchElement, OriginPointOne);
                //   OriginPointTwo = SafeSecurityHelperWrapper.ClientToScreen(this.TouchElement, OriginPointTwo);
            }

            return CursorOne != CursorTwo;

        }

    }


}
